#ifndef SJRPASSWORD_COMM_SHA256_HPP
#define SJRPASSWORD_COMM_SHA256_HPP

SJR_NAMESPACE_BEGIN

class EpubSha256 final {
public:
  constexpr static int Sha256Size = SHA256_DIGEST_LENGTH;

  explicit EpubSha256(unsigned char const *data = nullptr, int dataLen = 0)
      : mDataLen(dataLen), mData(data), mBuffer(Sha256Size), mContext() {}

  EpubSha256(EpubSha256 const &) = delete;
  EpubSha256 &operator=(EpubSha256 const &) = delete;

  unsigned char const *operator<<(std::vector<unsigned char> const &data) {
    this->init();
    this->update(data.data(), static_cast<int>(data.size()));
    return this->final();
  }

  void init() {
    SHA256_Init(&mContext);

    if ((mData == nullptr) || (mDataLen <= 0))
      return;

    this->update(mData, mDataLen);
  }

  void update(unsigned char const *data, int dataLen) {
    SHA256_Update(&mContext, data, dataLen);
  }

  unsigned char const * final() {
    SHA256_Final(&mBuffer[0], &mContext);
    return &mBuffer[0];
  }

  [[nodiscard]] int size() const {
    return static_cast<int>(mBuffer.size());
  }

private:
  int mDataLen;
  unsigned char const *mData;
  std::vector<unsigned char> mBuffer;

  SHA256_CTX mContext;
};

SJR_NAMESPACE_END

#endif//SJRPASSWORD_COMM_SHA256_HPP
